using System;
using System.Xml;

namespace Mbs.CastleContainer
{
    class PropertiesElementProcessor : AbstractXmlNodeProcessor
    {
        public override String Name
        {
            get { return "properties"; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="nodeList"></param>
        /// <param name="engine"></param>
        /// <example>
        /// <code>
        /// 	<properties>
        ///			<attributes>
        ///				<myAttribute>attributeValue</myAttribute>
        ///			</attributes>
        ///			<myProperty>propertyValue</myProperty>
        ///		</properties>
        /// </code>
        /// </example>
        public override void Process(IXmlProcessorNodeList nodeList, IXmlProcessorEngine engine)
        {
            XmlElement element = nodeList.Current as XmlElement;

            IXmlProcessorNodeList childNodes = new DefaultXmlProcessorNodeList(element.ChildNodes);

            while (childNodes.MoveNext())
            {
                // Properties processing its a little more complicated than usual
                // since we need to support all special tags (if,else,define...)
                // plus we need to register any regular element as a property asap
                // since we should support properties that reference other properties
                // i.e. <myprop2>#{prop1}</myprop2> 			
                if (engine.HasSpecialProcessor(childNodes.Current))
                {
                    // Current element its a special element so we bookmark it before processing it...
                    XmlNode current = childNodes.Current;

                    int pos = childNodes.CurrentPosition;

                    engine.DispatchProcessCurrent(childNodes);

                    // ...after processing we need to refresh childNodes
                    // to account for any special element that affects the element tree (if,choose...)
                    childNodes = new DefaultXmlProcessorNodeList(element.ChildNodes);

                    // we only care about changes in the tree from the current element and forward
                    // so if the new list is empty or smaller we just exit the loop
                    if (pos < childNodes.Count)
                    {
                        childNodes.CurrentPosition = pos;

                        // if the current element gets replaced in the new list we need to restart processing
                        // otherwise we just continue as usual
                        if (childNodes.Current != current)
                        {
                            childNodes.CurrentPosition -= 1;
                            continue;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    engine.DispatchProcessCurrent(childNodes);
                }

                if (IgnoreNode(childNodes.Current)) continue;

                XmlElement elem = GetNodeAsElement(element, childNodes.Current);

                engine.AddProperty(elem);
            }

            RemoveItSelf(element);
        }
    }
}
